package com.huahua.interceptor;

import com.huahua.enums.ExceptionEnum;
import com.huahua.annotation.Authority;
import com.huahua.component.AuthorityBeanPostProcess;
import com.huahua.entity.User;
import com.huahua.exception.BusinessException;
import com.huahua.interceptor.handler.AuthorityHandlerProcess;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义的权限拦截器
 *
 * @author huahua
 */
@Component
public class AuthorityInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            String name = handlerMethod.getMethod().getName();
            //拦截器想要获取容器中bean需要拿到bean工厂进行getBean()
            BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
            AuthorityHandlerProcess authorityProcess = factory.getBean("authorityProcess", AuthorityHandlerProcess.class);
            //从redis或者缓存中取得方法与权限关系
            Authority authority = AuthorityBeanPostProcess.map.get(name);
            if (authority != null) {
                //对当前用户进行权限校验
                //实际场景中，需要根据当前登录用户身份从数据库中查询其权限角色信息
                //获取用户信息。因为用户已经登录了，那么user的信息是保存在我们的缓存里的,token获取,这里写一个假数据。
                User user = new User();
                //模拟一个用户，设置其权限类型，1读，2读写
                user.setAuthority(2);
                user.setId(1);
                try {
                    //责任链调用,可以动态配置调用规则,即权限校验规则,
                    authorityProcess.process(user, authority);
                } catch (Exception e) {
                    //统一捕捉异常,返回错误信息
                    throw new BusinessException(ExceptionEnum.FORBIDDEN.getCode(),
                            ExceptionEnum.FORBIDDEN.getMsg(), "不允许的操作类型");
                }
            }
        }
        return true;
    }
}
